package com.snail.cloud.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.snail.cloud.dao.IotUserMapper;
import com.snail.cloud.model.BasePageInfo;
import com.snail.cloud.model.IotUser;
import com.snail.cloud.model.ResultData;
import com.snail.cloud.model.UserDetailsImpl;
import com.snail.cloud.model.vo.UserInsertVo;
import com.snail.cloud.model.vo.UserUpdateVo;
import com.snail.cloud.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import static com.snail.cloud.model.ResultCodeEnum.*;
import static com.snail.cloud.util.SendSmsUtil.PREFIX_CODE;

/**
 * @author MR.LHL
 * @date 2024/2/26
 */
@Service
public class UserServiceImpl implements UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private IotUserMapper iotUserMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        IotUser iotUser = iotUserMapper.selectUserVoByUsername(username);
        if (iotUser == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        UserDetailsImpl userDetails = new UserDetailsImpl(iotUser);
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
        System.out.println(authorities);
        return userDetails;
    }

    @Override
    public ResultData userAdd(UserInsertVo user) {
        if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())
                || !user.getPassword().equals(user.getConfirmPassword()) || StringUtils.isBlank(user.getCode())) {
            LOGGER.error("==========>[sila注册，参数错误]userData:{}", new Gson().toJson(user));
            return ResultData.error(BAD_REQUEST);
        }
        String o = (String) redisTemplate.opsForValue().get(PREFIX_CODE + user.getPhone());
        if (o == null) {
            LOGGER.error("==========>[验证码不存在] phone={}", user.getPhone());
            return ResultData.error(CODE_INVALID);
        }
        if (!user.getCode().equals(o)) {
            LOGGER.error("==========>[验证码不匹配] wechat={},code:{},codeDB:{}", user.getPhone(), user.getCode(), o);
            return ResultData.error(CODE_INVALID);
        }
        IotUser iotUser = iotUserMapper.selectByUsername(user.getUsername());
        if (iotUser != null) {
            return ResultData.error(USERNAME_EXISTS);
        }
        IotUser iotUser1 = iotUserMapper.selectByPhone(user.getPhone());
        if (iotUser1 != null) {
            return ResultData.error(PHONE_EXISTS);
        }
        IotUser newUser = new IotUser();
        newUser.setUsername(user.getUsername());
        newUser.setPhone(user.getPhone());
        newUser.setNickname(user.getNickname());
        newUser.setPassword(passwordEncoder.encode(user.getPassword()));
        newUser.setCreateTime(new Date());
        newUser.setLocked(false);
        newUser.setSalt(UUID.randomUUID().toString());
        iotUserMapper.insertSelective(newUser);
        return ResultData.success(newUser);
    }

    @Override
    public ResultData passwordUpdate(UserUpdateVo user, String token) {
        String oldPassword = user.getOldPassword();
        String newPassword = user.getConfirmPassword();
        String confirmPassword = user.getConfirmPassword();
        if (StringUtils.isBlank(newPassword) || StringUtils.isBlank(confirmPassword)
                || !newPassword.equals(confirmPassword)) {
            LOGGER.error("参数错误:requestData:{}", new Gson().toJson(user));
            return ResultData.error(BAD_REQUEST);
        }

        IotUser iotUser = iotUserMapper.selectByPrimaryKey(user.getUserId());
        if (iotUser == null) {
            LOGGER.error("用户不存在，userId:{}", user.getUserId());
            return ResultData.error(BAD_REQUEST);
        }
        if (StringUtils.isNotBlank(iotUser.getPassword())) {
            if (StringUtils.isBlank(oldPassword)) {
                LOGGER.error("参数错误，该用户有旧密码，需要传入旧密码参数");
                return ResultData.error(BAD_REQUEST);
            }
            String encode = passwordEncoder.encode(oldPassword);
            if (passwordEncoder.matches(iotUser.getPassword(), encode)) {
                LOGGER.info("==========>[修改密码，旧密码验证成功] oldPassword={},newPassword={}", oldPassword, newPassword);
                iotUser.setPassword(passwordEncoder.encode(newPassword));
                iotUser.setSalt(UUID.randomUUID().toString());
                iotUser.setUpdateTime(new Date());
                iotUserMapper.updateByPrimaryKeySelective(iotUser);
                return ResultData.success();
            } else {
                LOGGER.error("==========>[修改密码失败，旧密码验证失败]");
                return ResultData.error(INVALID_OLD_PASSWORD);
            }
        } else {
            LOGGER.info("==========>[修改密码，用户无旧密码] userId={},newPassword={}", iotUser.getUserId(), newPassword);
            iotUser.setPassword(passwordEncoder.encode(newPassword));
            iotUser.setUpdateTime(new Date());
            iotUser.setSalt(UUID.randomUUID().toString());
            iotUserMapper.updateByPrimaryKeySelective(iotUser);
            return ResultData.success();
        }
    }

    @Override
    public ResultData passwordForget(UserInsertVo user) {
        String password = user.getPassword();
        String confirmPassword = user.getConfirmPassword();
        String phone = user.getPhone();
        String code = user.getCode();

        if (StringUtils.isAnyBlank(password, confirmPassword, phone, code) || !password.equals(confirmPassword)) {
            LOGGER.error("参数错误:requestData:{}", new Gson().toJson(user));
            return ResultData.error(BAD_REQUEST);
        }

        String o = (String) redisTemplate.opsForValue().get(PREFIX_CODE + user.getPhone());
        if (o == null) {
            LOGGER.error("==========>[验证码不存在] phone={}", user.getPhone());
            return ResultData.error(CODE_INVALID);
        }
        if (!code.equals(o)) {
            LOGGER.error("==========>[验证码不匹配] wechat={},code:{},codeDB:{}", user.getPhone(), user.getCode(), o);
            return ResultData.error(CODE_INVALID);
        }

        IotUser iotUser = iotUserMapper.selectByPhone(phone);
        if (iotUser == null) {
            LOGGER.error("用户不存在，userId:{}", phone);
            return ResultData.error(PHONE_NOT_EXISTS);
        }
        String encode = passwordEncoder.encode(password);
        iotUser.setPassword(encode);
        iotUser.setSalt(UUID.randomUUID().toString());
        iotUser.setUpdateTime(new Date());
        iotUserMapper.updateByPrimaryKeySelective(iotUser);
        return ResultData.success();
    }

    @Override
    public ResultData getUserPage(BasePageInfo info) {
        PageHelper.startPage(info.getPageNum(), info.getPageSize());
        List<IotUser> list = iotUserMapper.selectAll();
        return ResultData.success(new PageInfo<>(list));
    }
}
